use std::collections::HashMap;

use common_base::{
    prelude::*,
    serde::{self, Serialize},
    sqlx::{mysql::MySqlRow, Column, Row},
};

use crate::data::{dataset::data_status::DataStatus, DataValue};

#[derive(Debug, Serialize)]
#[serde(crate = "self::serde")]
#[serde(rename_all = "camelCase")]
pub struct Rowset {
    pub(crate) data_values: HashMap<String, DataValue>,
    pub(crate) data_status: DataStatus,
}

impl Default for Rowset {
    fn default() -> Self {
        Self {
            data_values: Default::default(),
            data_status: DataStatus::Normal,
        }
    }
}

impl Rowset {
    pub fn put_data_value(&mut self, col_name: &str, data_value: DataValue) {
        self.data_values.insert(col_name.to_owned(), data_value);
    }
}

impl TryFrom<MySqlRow> for Rowset {
    type Error = ErrorCode;

    fn try_from(db_row: MySqlRow) -> std::result::Result<Self, Self::Error> {
        let mut rowset = Rowset::default();
        for col in db_row.columns() {
            let value = db_row.try_get_raw(col.ordinal())?;

            let data_value: DataValue = (col.ordinal(), value).try_into()?;
            rowset.put_data_value(col.name(), data_value);
        }
        rowset.data_status = DataStatus::Normal;
        Ok(rowset)
    }
}
